package com.example;

/**
 * @Author loubobooo
 * @Description #174. 地下城游戏
 * @Date 2022/04/5
 */
public class DungeonGame {


    /**
     * 一些恶魔抓住了公主（P）并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。
     * 我们英勇的骑士（K）最初被安置在左上角的房间里，他必须穿过地下城并通过对抗恶魔来拯救公主。
     *
     * 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下，他会立即死亡。
     *
     * 有些房间由恶魔守卫，因此骑士在进入这些房间时会失去健康点数（若房间里的值为负整数，则表示骑士将损失健康点数）；
     * 其他房间要么是空的（房间里的值为 0），要么包含增加骑士健康点数的魔法球（若房间里的值为正整数，则表示骑士将增
     * 加健康点数）。
     *
     * 为了尽快到达公主，骑士决定每次只向右或向下移动一步。
     *
     * 编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
     *
     * 例如，考虑到如下布局的地下城，如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下，则骑士的初始健康点数至少为 7。
     *
     * -2 (K)	-3	3
     * -5	-10	1
     * 10	30	-5 (P)
     * @param dungeon
     * @return
     */
    public int calculateMinimumHP(int[][] dungeon) {
        if (dungeon == null || dungeon.length == 0) {
            return 0;
        }
        int m = dungeon.length;
        int n = dungeon[0].length;
        // dp含义：表示需要最少的血量
       int[][] dp = new int[m][n];
        // 初始化，保证还有1滴血
        dp[m-1][n-1] = Math.max(1, -dungeon[m-1][n-1] + 1);
        for (int i = m - 2; i >= 0; i--) {
            // dp = -10	 1       ==>  -10  5
            //	     30	-5 (P)         30  6
            dp[i][n - 1] = Math.max(1, dp[i + 1][n - 1] - dungeon[i][n - 1]);
        }
        for (int i = n - 2; i >=0 ; i--) {
            // 保证生存每个格子至少1滴血
            // dp = -10	1        ==>  -10  5
            //	     30	-5 (P)         1  6
            dp[m - 1][i] = Math.max(1, dp[m - 1][i + 1] - dungeon[m - 1][i]);
        }

        for (int i =  m - 2; i >= 0 ; i--) {
            for (int j = n - 2; j >= 0 ; j--) {
                // dp = -10	1        ==>  -10(min 11)  5
                //	     30	-5 (P)         1  6
                dp[i][j] = Math.max(1, Math.min(dp[i + 1][j], dp[i][j + 1]) -dungeon[i][j]);
            }
        }
        return dp[0][0];
    }

    public static void main(String[] args) {
        DungeonGame dungeonGame = new DungeonGame();
        int[][] nums = new int[][]{{-2,-3, 3}, {-5, -10,1},{10,30,-5}};
        dungeonGame.calculateMinimumHP(nums);
    }
}
